package org.jetbrains.plugins.scala.lang.psi.impl.base

import com.intellij.openapi.extensions.ExtensionPointName
import org.jetbrains.plugins.scala.lang.psi.api.base.{ScInterpolatedStringLiteral, ScReference}
import org.jetbrains.plugins.scala.lang.psi.types.result.TypeResult

/**
  * This is the stub that a plugin should extend in order to genereate a result type for macro invocations on
  * interpolated strings.
  *
  */
abstract class InterpolatedStringMacroTypeProvider {

  /**
    * This method is used to decide whether an interpolated string expression is a macro and its type could be infered
    * by this plugin.
    *
    * @param ref invoked function on interpolated string
    * @return if this interpolated string expression is a macro and its type inference is handled by the plugin
    */
  def handlesInterpolatedString(ref: ScReference): Boolean

  /**
    * This method allows to infer a type for code generated by a macro that is invoked on an interpolated string.
    *
    * @param pat the interpolated string literal that will be transformed by a macro
    * @return The resulting type of the code generated by a macro
    */
  def inferExpressionType(pat: ScInterpolatedStringLiteral): TypeResult
}

object InterpolatedStringMacroTypeProvider {
  private val CLASS_NAME = "org.intellij.scala.interpolatedStringMacroTypeProvider"

  val EP_NAME: ExtensionPointName[InterpolatedStringMacroTypeProvider] = ExtensionPointName.create(CLASS_NAME)

  def getTypeProvider(ref: ScReference): Option[InterpolatedStringMacroTypeProvider] =
    EP_NAME.getExtensions.find(_.handlesInterpolatedString(ref))
}